package com.example.cloud.service.system.impl;

import com.alibaba.fastjson.JSONArray;
import com.example.cloud.constants.StateConstants;
import com.example.cloud.dao.system.MenuRepository;
import com.example.cloud.dao.mongdb.basic.info.MongoMenuRepository;
import com.example.cloud.model.system.Menu;
import com.example.cloud.model.system.Role;
import com.example.cloud.service.system.MenuService;
import com.example.cloud.utils.TreeUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * Created by wangtao on 2018/2/3.
 */
@Service
public class MenuServiceImpl implements MenuService {

    private static final Logger logger = Logger.getLogger(MenuServiceImpl.class);

    @Autowired
    private MenuRepository menuRepository;

    @Autowired
    private MongoMenuRepository mongoMenuRepository;

    @Override
    public List<Menu> findAllFromCache() {
        return mongoMenuRepository.findAll();
    }

    @Override
    public List<Menu> findAllByMenuFromCache() {
        return mongoMenuRepository.findByIsShow(1);
    }

    @Override
    public List<Menu> findAllByButtonFromCache() {
        return mongoMenuRepository.findByType(StateConstants.MENU_TYPE_BUTTON);
    }

    @Override
    public JSONArray createMenuTree(List<Menu> menus, Integer type) {
        return TreeUtil.buildMenuTree(menus, type);
    }

    /**
     *
     * @param parentId
     * @return
     */
    @Override
    public List<Menu> findAllButtonFromCache(long parentId) {
        return mongoMenuRepository.findByParentIdAndTypeOrderBySort(parentId,2);
    }

    @Override
    public List<Menu> getMenuList(Role role, Menu menu) {
        // 拥有权限的ID集合
        List<Long> ids = role.getMenus().stream().map(Menu::getId).collect(toList());
        // 如果当前选中节点已经包含在拥有权限中
        if(ids.contains(menu.getId())){
            List<Long> delIds = new ArrayList<Long>();
            delIds.add(menu.getId());
            // 递归移除当前节点及其子节点
            getChildNodesId(delIds, menu);
            // 获取删除节点
            List<Menu> list = role.getMenus().stream().filter(roleMenu -> delIds.contains(roleMenu.getId())).collect(toList());
            if(!list.isEmpty()){
                role.getMenus().removeAll(list);
            }
        }else{
            // 添加当前节点
            role.getMenus().add(menu);
            // 递归添加父节点
            addParentNode(ids, role.getMenus(), menu);
            // 递归添加子节点
            addChildNode(ids, role.getMenus(), menu);
        }
        return role.getMenus();
    }

    /**
     * 判断是否添加当前节点的父节点对象
     * @param menu
     * @param menus
     * @param ids
     * @return
     */
    public void addParentNode(List<Long> ids, List<Menu> menus, Menu menu){
        Long id = menu.getParentId();
        if(id != null && !ids.contains(id)){
            Menu parent = mongoMenuRepository.findOne(id);
            if(parent != null){
                menus.add(parent);
                addParentNode(ids, menus, parent);
            }
        }
    }

    /**
     * @param menu
     * @param menus
     * @param ids
     * @return
     */
    public void addChildNode(List<Long> ids, List<Menu> menus, Menu menu){
        List<Menu> list = menuRepository.findByParentIdAndDeleteFlag(menu.getId(), 0);
        for (Menu m : list) {
            if(!ids.contains(m.getId())){
                menus.add(m);
                addChildNode(ids, menus, m);
            }
        }
    }

    /**
     * 获取当前节点下所有子节点集合
     * @return
     */
    public void getChildNodesId(List<Long> childIds, Menu menu){
        menu.getChildren().forEach(child -> {
            childIds.add(child.getId());
            getChildNodesId(childIds, child);
        });
    }

    @Override
    public void loadCache() {
        List<Menu> list = menuRepository.findAll();
        if(!list.isEmpty()){
            mongoMenuRepository.save(list);
            logger.info("*******************菜单已全部同步缓存*******************");
        }
    }
}
